/**
 *  (c)
 * <p>
 *
 * <p>
 *
 */

package com.nn.smart.bus.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.nn.smart.bus.commons.mybatis.service.impl.BaseServiceImpl;
import com.nn.smart.bus.commons.tools.enums.SuperAdminEnum;
import com.nn.smart.bus.commons.tools.exception.ErrorCode;
import com.nn.smart.bus.commons.tools.exception.NNException;
import com.nn.smart.bus.commons.tools.redis.RedisKeys;
import com.nn.smart.bus.commons.tools.redis.RedisUtils;
import com.nn.smart.bus.commons.tools.redis.UserDetailRedis;
import com.nn.smart.bus.commons.tools.security.user.SecurityUser;
import com.nn.smart.bus.commons.tools.security.user.UserDetail;
import com.nn.smart.bus.commons.tools.utils.ConvertUtils;
import com.nn.smart.bus.commons.tools.utils.Result;
import com.nn.smart.bus.commons.tools.utils.TreeUtils;
import com.nn.smart.bus.dao.SysDeptDao;
import com.nn.smart.bus.dto.epdc.GridForLeaderRegisterDTO;
import com.nn.smart.bus.dto.epdc.form.UserSysDeptInfoFormDTO;
import com.nn.smart.bus.dto.epdc.result.UserSysDeptInfoResultDTO;
import com.nn.smart.bus.entity.SysDeptEntity;
import com.nn.smart.bus.service.SysDeptService;
import com.nn.smart.bus.service.SysUserService;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.nn.smart.bus.commons.tools.constant.*;
import com.nn.smart.bus.dto.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 部门管理
 *
 * @author nanning
 * @since 1.0.0
 */
@Slf4j
@Service
public class SysDeptServiceImpl extends BaseServiceImpl<SysDeptDao, SysDeptEntity> implements SysDeptService {
    @Autowired
    private SysUserService sysUserService;

    @Autowired
    private UserDetailRedis userDetailRedis;

    @Autowired
    private RedisUtils redisUtils;

    private static final Logger logger = LoggerFactory.getLogger(SysDeptServiceImpl.class);

    @Override
    public List<SysDeptDTO> list(Map<String, Object> params) {
        //普通管理员，只能查询所属部门及子部门的数据
        UserDetail user = SecurityUser.getUser();
        if (user.getSuperAdmin() == SuperAdminEnum.NO.value()) {
            params.put("deptIdList", getSubDeptIdList(user.getDeptId()));
        }

        List<SysDeptEntity> entityList = baseDao.getList(params);

        List<SysDeptDTO> dtoList = ConvertUtils.sourceToTarget(entityList, SysDeptDTO.class);

        return TreeUtils.build(dtoList);
    }

    @Override
    public List<SysSimpleDeptDTO> subList(String pid) {
        QueryWrapper<SysDeptEntity> wrapper = new QueryWrapper<>();
        wrapper.eq("PID", pid)
                .ne("TYPE_KEY", "district_dept")
                .ne("TYPE_KEY", "street_dept")
                .select(FieldConstant.ID, FieldConstant.NAME)
                .orderByAsc(FieldConstant.NAME);
        List<SysDeptEntity> entities = this.baseDao.selectList(wrapper);
        return ConvertUtils.sourceToTarget(entities, SysSimpleDeptDTO.class);
    }

    @Override
    public SysDeptDTO get(Long id) {
        //超级管理员，部门ID为null
        if (id == null) {
            return null;
        }

        SysDeptEntity entity = baseDao.getById(id);

        return ConvertUtils.sourceToTarget(entity, SysDeptDTO.class);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void save(SysDeptDTO dto) {
        String partyCode = dto.getPartyCode();
        if (StringUtils.isNotBlank(partyCode)) {
            if (getCodeCount(dto) > 0) {
                throw new NNException("您输入的编码已存在");
            }
        }

        SysDeptEntity entity = ConvertUtils.sourceToTarget(dto, SysDeptEntity.class);

        entity.setPids(getPidList(entity.getPid()));
        insert(entity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(SysDeptDTO dto) {
        String partyCode = dto.getPartyCode();
        if (StringUtils.isNotBlank(partyCode)) {
            if (getCodeCount(dto) > 0) {
                throw new NNException("您输入的编码已存在");
            }
        }

        SysDeptEntity entity = ConvertUtils.sourceToTarget(dto, SysDeptEntity.class);

        //上级部门不能为自身
        if (entity.getId().equals(entity.getPid())) {
            throw new NNException(ErrorCode.SUPERIOR_DEPT_ERROR);
        }

        entity.setPids(getPidList(entity.getPid()));
        updateById(entity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(Long id) {
        //判断是否有子部门
        List<Long> subList = getSubDeptIdList(id);
        if (subList.size() > 1) {
            throw new NNException(ErrorCode.DEPT_SUB_DELETE_ERROR);
        }

        //判断部门下面是否有用户
        int count = sysUserService.getCountByDeptId(id);
        if (count > 0) {
            throw new NNException(ErrorCode.DEPT_USER_DELETE_ERROR);
        }

        //逻辑删除
        logicDelete(new Long[]{id}, SysDeptEntity.class);
    }

    @Override
    public List<Long> getSubDeptIdList(Long id) {
        List<Long> deptIdList = baseDao.getSubDeptIdList("%" + id + "%");
        deptIdList.add(id);

        return deptIdList;
    }

    /**
     * 获取所有上级部门ID
     *
     * @param pid 上级ID
     */
    private String getPidList(Long pid) {
        //顶级部门，无上级部门
        if (Constant.DEPT_ROOT.equals(pid)) {
            return Constant.DEPT_ROOT + "";
        }

        //所有部门的id、pid列表
        List<SysDeptEntity> deptList = baseDao.getIdAndPidList();

        //list转map
        Map<Long, SysDeptEntity> map = new HashMap<>(deptList.size());
        for (SysDeptEntity entity : deptList) {
            map.put(entity.getId(), entity);
        }

        //递归查询所有上级部门ID列表
        List<Long> pidList = new ArrayList<>();
        getPidTree(pid, map, pidList);

        return StringUtils.join(pidList, ",");
    }

    private void getPidTree(Long pid, Map<Long, SysDeptEntity> map, List<Long> pidList) {
        //顶级部门，无上级部门
        if (Constant.DEPT_ROOT.equals(pid)) {
            return;
        }

        //上级部门存在
        SysDeptEntity parent = map.get(pid);
        if (parent != null) {
            getPidTree(parent.getPid(), map, pidList);
        }

        pidList.add(pid);
    }

    @Override
    public Result<List<Long>> listGridIdByPid(Long pid) {
        List<Long> deptIdList = this.baseDao.listGridIdByPid(pid);
        return new Result().ok(deptIdList);
    }

    @Override
    public Result<CompleteDeptDTO> getCompleteDept(String gridId) {
        Long gridIdL = null;
        try {
            gridIdL = Long.parseLong(gridId.trim());
        } catch (Exception e) {
            log.error("->getCompleteDept:::网格ID格式转换异常:::grid->{}", gridId);
        }
        if (null == gridId) {
            return new Result().error("参数格式异常");
        }
        CompleteDeptDTO completeDept = this.baseDao.getCompleteDept(gridIdL);
        return new Result().ok(completeDept);
    }

    @Override
    public Result<ParentAndAllDeptDTO> getParentAndAllDept(String deptId) {
        Long deptIdL = null;
        try {
            deptIdL = Long.parseLong(deptId.trim());
        } catch (Exception e) {
            log.error("->getCompleteDept:::部门ID格式转换异常:::deptId->{}", deptId);
        }
        if (null == deptIdL) {
            return new Result().error("参数格式异常");
        }
        CompleteDeptDTO completeDept = this.baseDao.getParentAndAllDept(deptIdL);
        ParentAndAllDeptDTO parentAndAllDeptDTO = new ParentAndAllDeptDTO();

        if (completeDept != null) {
            parentAndAllDeptDTO.setGrid(StringUtils.isNotEmpty(completeDept.getGrid()) ? completeDept.getGrid() : "");
            parentAndAllDeptDTO.setGridId(completeDept.getGridId() != null && completeDept.getGridId() != 0 ? completeDept.getGridId() : null);
            // 父所有部门（包含街道、社区）
            String deptNames = (StringUtils.isNotEmpty(completeDept.getDistrict()) ? completeDept.getDistrict() + "-" : "");
            deptNames += (StringUtils.isNotEmpty(completeDept.getStreet()) ? completeDept.getStreet() + "-" : "");
            deptNames += (StringUtils.isNotEmpty(completeDept.getCommunity()) ? completeDept.getCommunity() + "-" : "");
            String deptIds = (completeDept.getDistrictId() != null && completeDept.getDistrictId() != 0 ? completeDept.getDistrictId().toString() + "," : "");
            deptIds += (completeDept.getStreetId() != null && completeDept.getStreetId() != 0 ? completeDept.getStreetId().toString() + "," : "");
            deptIds += (completeDept.getCommunityId() != null && completeDept.getCommunityId() != 0 ? completeDept.getCommunityId().toString() + "," : "");
            parentAndAllDeptDTO.setParentDeptIds(!"".equals(deptIds) ? deptIds.substring(0, deptIds.length() - 1) : "");
            parentAndAllDeptDTO.setParentDeptNames(!"".equals(deptNames) ? deptNames.substring(0, deptNames.length() - 1) : "");
            // 所有部门（包含街道、社区、网格）
            deptNames += (StringUtils.isNotEmpty(completeDept.getGrid()) ? completeDept.getGrid() : "");
            deptIds += (completeDept.getGridId() != null && completeDept.getGridId() != 0 ? completeDept.getGridId().toString() : "");
            parentAndAllDeptDTO.setAllDeptIds(deptIds);
            parentAndAllDeptDTO.setAllDeptNames(deptNames);
        } else {
            return new Result().error("部门Id错误");
        }


        return new Result().ok(parentAndAllDeptDTO);
    }

    @Override
    public List<GridForLeaderRegisterDTO> selectListGridForLeader(List<String> gridIdList) {
        return this.baseDao.selectListGridForLeader(gridIdList);
    }

    @Override
    public Map<String, String> getIdByCode(String partyCode) {
        QueryWrapper<SysDeptEntity> wrapper = new QueryWrapper<>();
        wrapper.select("id");
        wrapper.eq("party_code", partyCode);
        SysDeptEntity sysDeptEntity = baseDao.selectOne(wrapper);
        Map<String, String> map = new HashMap<>();
        map.put("id", sysDeptEntity.getId().toString());
        return map;
    }

    @Override
    public Integer getCodeCount(SysDeptDTO dto) {
        QueryWrapper<SysDeptEntity> wrapper = new QueryWrapper<>();
        wrapper.eq("party_code", dto.getPartyCode());
        Long id = dto.getId();
        wrapper.ne(id != null, "id", dto.getId());
        return baseDao.selectCount(wrapper);
    }

    @Override
    public Integer getAreaCodeCount(SysDeptDTO dto) {
        QueryWrapper<SysDeptEntity> wrapper = new QueryWrapper<>();
        wrapper.eq("area_code", dto.getAreaCode());
        Long id = dto.getId();
        wrapper.ne(id != null, "id", dto.getId());
        return baseDao.selectCount(wrapper);
    }

    @Override
    public Result<String> getParentDeptIds(Long deptId) {
        return new Result<String>().ok(getPidList(deptId));
    }

    @Override
    public Result<List<String>> getCompleteDeptList(Long deptId) {
        CompleteDeptDTO completeDept = this.baseDao.getCompleteDept(deptId);
        List<String> list = Lists.newArrayList();
        list.add(completeDept.getDistrict());
        list.add(completeDept.getStreet());
        list.add(completeDept.getCommunity());
        list.add(completeDept.getGrid());
        return new Result().ok(list);
    }

    @Override
    public DeptOption getUserDeptOption() {
        return getUserDeptOption(SecurityUser.getUserId());
    }


    /**
     * 根据userId，从redis取出用户部门层级关系（街道-社区-网格）
     *
     * @param userId
     * @return com.nn.smart.bus.dto.DeptOption
     * @author nanning
     */
    private DeptOption getUserDeptOption(Long userId) {
        String deptOptionKey = RedisKeys.getAdminUserDeptOptionKey(userId);
        Object obj = redisUtils.get(deptOptionKey);
        if (null == obj) {
            this.packageUserDeptOption(userId);
            obj = redisUtils.get(deptOptionKey);
        }
        return (DeptOption) obj;
    }

    @Override
    public DeptOption getAllDeptOptionByLoginUser() {
        Long userId = SecurityUser.getUserId();
        String deptOptionKey = RedisKeys.getAllAdminUserDeptOptionKey(userId);
        Object obj = redisUtils.get(deptOptionKey);
        if (null == obj) {
            this.packageAllUserDeptOption(userId);
            obj = redisUtils.get(deptOptionKey);
        }
        return (DeptOption) obj;
    }

    @Override
    public DeptOption getMiddleByLoginUser() {
        DeptOption result = getUserDeptOption(SecurityUser.getUserId());
        List<JSONObject> options = result.getOptions();
        if (options.isEmpty()) {
            return result;
        }
        // 代表存在子级机构的json key
        String childJsonOptionKey = "children";
        // 一个街道机构
        JSONObject streetOption;
        // 一个街道下所有社区机构
        JSONArray communityOptionArray;
        // 一个社区机构
        JSONObject communityOption;
        // 循环所有街道
        for (int i = options.size() - NumConstant.ONE; i >= NumConstant.ZERO; i--) {
            // 取出一个街道
            streetOption = options.get(i);
            // 街道有children，代表有下级社区（没有children的，其实是区直）
            if (null != streetOption.get(childJsonOptionKey)) {
                // 获取该街道的所有社区
                communityOptionArray = streetOption.getJSONArray(childJsonOptionKey);
                if (!communityOptionArray.isEmpty()) {
                    // 社区不为空，循环所有社区
                    for (int j = 0; j < communityOptionArray.size(); j++) {
                        // 取出一个社区
                        communityOption = communityOptionArray.getJSONObject(j);
                        // 社区有children，代表有下级网格，
                        if (null != communityOption.get(childJsonOptionKey)) {
                            // 移除网格
                            communityOption.remove(childJsonOptionKey);
                        }
                    }
                }
            } else {
                // 移除区直机构
                options.remove(i);
            }
        }
        return result;
    }

    @Override
    public DeptOption getStreetByLoginUser() {
        DeptOption result = getUserDeptOption(SecurityUser.getUserId());
        List<JSONObject> options = result.getOptions();
        if (options.isEmpty()) {
            return result;
        }
        // 代表存在子级机构的json key
        String childJsonOptionKey = "children";
        // 一个街道机构
        JSONObject streetOption;
        // 循环所有街道
        for (int i = options.size() - NumConstant.ONE; i >= NumConstant.ZERO; i--) {
            // 取出一个街道
            streetOption = options.get(i);
            // 街道有children，代表有下级社区（没有children的，其实是区直）
            if (null != streetOption.get(childJsonOptionKey)) {
                // 若街道有下级机构（社区），移除社区
                streetOption.remove(childJsonOptionKey);
            } else {
                // 移除区直机构（有些街道还没创建社区，也被移除）
                options.remove(i);
            }
        }
        return result;
    }

    /**
     * @param formDTO
     * @return java.util.List<com.nn.smart.bus.dto.epdc.result.UserSysDeptInfoResultDTO>
     * @author nanning
     * @Description
     * @Date 2019/12/4 19:43
     **/
    @Override
    public List<UserSysDeptInfoResultDTO> listUserSysDeptInfoResultDTO(UserSysDeptInfoFormDTO formDTO) {
        if (CollUtil.isEmpty(formDTO.getDeptIdList())) {
            Long userId = SecurityUser.getUserId();
            // 查询当前用户所具有的的数据权限
            UserDetail userDetail = userDetailRedis.get(userId);
            // 用户拥有的所有部门权限
            List<Long> dataScopeDeptList = userDetail.getDeptIdList();
            formDTO.setDeptIdList(dataScopeDeptList);
        }
        List<UserSysDeptInfoResultDTO> list = baseDao.selectListUserSysDeptInfo(formDTO);
        // 处理记录，赋值parentNames
        for (UserSysDeptInfoResultDTO resultDTO : list) {
            if (resultDTO.getPid() != 0) {
                String parentNames = "";
                String street = "";
                String community = "";
                String grid = "";
                String[] pids = resultDTO.getPids().split(",");
                for (String id : pids) {
                    SysDeptEntity deptEntity = baseDao.getById(Long.valueOf(id));
                    parentNames += deptEntity.getName() + "-";
                    if (("street_party").equals(deptEntity.getTypeKey())) {
                        street = deptEntity.getName();
                    } else if (("community_party").equals(deptEntity.getTypeKey())) {
                        community = deptEntity.getName();
                    } else if (("grid_party").equals(deptEntity.getTypeKey())) {
                        grid = deptEntity.getName();
                    }
                }
                parentNames = parentNames.substring(0, parentNames.length() - 1);
                resultDTO.setParentNames(parentNames);
                resultDTO.setStreet(street);
                resultDTO.setCommunity(community);
                if (StringUtils.isNotBlank(grid)) {
                    resultDTO.setGrid(grid);
                }
            }
        }
        return list;
    }


    @Override
    public void packageUserDeptOption(Long userId) {
        packageDeptOptionByUser(userId, false);
    }

    private void packageAllUserDeptOption(Long userId) {
        packageDeptOptionByUser(userId, true);
    }

    private void packageWorkLogsUserDeptOption(Long userId) {
        packageWorkLogDeptOptionByUser(userId);
    }

    private void packageWorkLogDeptOptionByUser(Long userId) {
        UserDetail userDetail = userDetailRedis.get(userId);
        // 用户拥有的所有部门权限
        List<Long> dataScopeDeptList = userDetail.getDeptIdList();
        if (CollUtil.isEmpty(dataScopeDeptList)) {
            return;
        }
        // 通过用户部门权限 获取第一级部门节点
        List<SysDeptEntity> headDepts = baseDao.selectListHeadDeptNode(dataScopeDeptList);


        // 某个部门id 声明变量，方便操作数据
        Long deptId;

        // 存放上级节点的主键，查询下级节点用
        List<Long> parentDeptIdList = Lists.newArrayList();
        // 所有父级节点 此处为第一次获取，为顶级节点，相当于市区
        JSONArray parentNodeArray = new JSONArray();
        JSONObject node;
        for (int i = 0; i < headDepts.size(); i++) {
            // 父节点主键
            deptId = headDepts.get(i).getId();
            parentDeptIdList.add(deptId);

            node = new JSONObject();
            node.put("label", headDepts.get(i).getName());
            node.put("typeKey", headDepts.get(i).getTypeKey());
            node.put("value", String.valueOf(deptId));
            parentNodeArray.add(node);
        }
        // 用于存放 每次组装好的 某一级节点。页面只需展示三级，所以没有存放顶级节点（市区）
        List<JSONArray> cache = Lists.newArrayList();
        //判断用户所属部门是否属于一级部门 属于则添加头
        SysDeptEntity sysDeptEntity = baseDao.selectById(SecurityUser.getDeptId());
        if(0L == sysDeptEntity.getPid()){
            cache.add(parentNodeArray);
        }
        Map<String, Object> object;
        while (CollUtil.isNotEmpty(dataScopeDeptList) && CollUtil.isNotEmpty(parentDeptIdList)) {
            // 通过上级节点组装所有下级节点
            object = this.packageChildrenNodeArray(parentNodeArray, dataScopeDeptList, parentDeptIdList);

            dataScopeDeptList = (List<Long>) object.get("scope");
            parentDeptIdList = (List<Long>) object.get("pids");

            parentNodeArray = (JSONArray) object.get("node");
            cache.add(parentNodeArray);
        }

        DeptOption option = new DeptOption();
        option.setOptions(cache.get(0));

        redisUtils.set(RedisKeys.getWorkLogUserDeptOptionKey(userId), option);
    }

    /**
     * 组装部门层级结构
     *
     * @param userId         用户id
     * @param packageAllDept 是否组装完整层级结构，否 则组装后三级
     * @return void
     * @author nanning
     */
    private void packageDeptOptionByUser(long userId, boolean packageAllDept) {
        UserDetail userDetail = userDetailRedis.get(userId);
        // 用户拥有的所有部门权限
        List<Long> dataScopeDeptList = userDetail.getDeptIdList();
        if (CollUtil.isEmpty(dataScopeDeptList)) {
            return;
        }
        // 通过用户部门权限 获取第一级部门节点
        List<SysDeptEntity> headDepts = baseDao.selectListHeadDeptNode(dataScopeDeptList);
        if (CollUtil.isEmpty(headDepts)) {
            return;
        }
        // 某个部门id 声明变量，方便操作数据
        Long deptId;

        // 存放上级节点的主键，查询下级节点用
        List<Long> parentDeptIdList = Lists.newArrayList();
        // 所有父级节点 此处为第一次获取，为顶级节点，相当于市区
        JSONArray parentNodeArray = new JSONArray();
        JSONObject node;
        for (int i = 0; i < headDepts.size(); i++) {
            // 父节点主键
            deptId = headDepts.get(i).getId();
            parentDeptIdList.add(deptId);

            node = new JSONObject();
            node.put("label", headDepts.get(i).getName());
            node.put("typeKey", headDepts.get(i).getTypeKey());
            node.put("value", String.valueOf(deptId));
            parentNodeArray.add(node);
        }
        // 用于存放 每次组装好的 某一级节点。页面只需展示三级，所以没有存放顶级节点（市区）
        List<JSONArray> cache = Lists.newArrayList();
        if (packageAllDept) {
            cache.add(parentNodeArray);
        }
        Map<String, Object> object;
        while (CollUtil.isNotEmpty(dataScopeDeptList) && CollUtil.isNotEmpty(parentDeptIdList)) {
            // 通过上级节点组装所有下级节点
            object = this.packageChildrenNodeArray(parentNodeArray, dataScopeDeptList, parentDeptIdList);

            dataScopeDeptList = (List<Long>) object.get("scope");
            parentDeptIdList = (List<Long>) object.get("pids");

            parentNodeArray = (JSONArray) object.get("node");
            cache.add(parentNodeArray);
        }

        DeptOption option = new DeptOption();
        option.setOptions(cache.get(0));

        if (packageAllDept) {
            redisUtils.set(RedisKeys.getAllAdminUserDeptOptionKey(userId), option);
        } else {
            redisUtils.set(RedisKeys.getAdminUserDeptOptionKey(userId), option);
        }

    }

    /**
     * 组装下级结构节点
     *
     * @param allParentNode     所有的上级机构节点
     * @param dataScopeDeptList 拥有数据权限的部门
     * @param parentDeptIdList  上级部门id
     * @return java.util.Map<java.lang.String, java.lang.Object>
     * @author nanning
     * @date 2019/11/29 10:27
     */
    private Map<String, Object> packageChildrenNodeArray(JSONArray allParentNode, List<Long> dataScopeDeptList, List<Long> parentDeptIdList) {

        List<SysDeptEntity> childDepts = baseDao.selectChildrenDeptNode(dataScopeDeptList, parentDeptIdList);

        parentDeptIdList = Lists.newArrayList();

        // 用于存储所有子节点
        JSONArray allChildrenNode = new JSONArray();
        // 某个父节点下所有的子节点
        JSONArray childrenNodeList;
        // 单个 子节点
        JSONObject nodeChild;

        // 单个 父节点
        JSONObject nodeParent;
        Long deptId;

        for (int i = 0; i < allParentNode.size(); i++) {

            nodeParent = allParentNode.getJSONObject(i);
            // 用于存储 一个父节点的所有下级节点
            childrenNodeList = new JSONArray();

            for (int j = 0; j < childDepts.size(); j++) {
                deptId = childDepts.get(j).getId();

                if (nodeParent.get("value").equals(String.valueOf(childDepts.get(j).getPid()))) {
                    nodeChild = new JSONObject();
                    nodeChild.put("label", childDepts.get(j).getName());
                    nodeChild.put("typeKey", childDepts.get(j).getTypeKey());
                    nodeChild.put("value", String.valueOf(deptId));
                    childrenNodeList.add(nodeChild);

                    allChildrenNode.add(nodeChild);
                    parentDeptIdList.add(deptId);
                }
            }
            if (childrenNodeList.size() > 0) {
                nodeParent.put("children", childrenNodeList);
            }
        }

        List<Long> newDataScopeList = Lists.newArrayList();
        for (int i = 0; i < dataScopeDeptList.size(); i++) {
            deptId = dataScopeDeptList.get(i);
            if (!parentDeptIdList.contains(deptId)) {
                newDataScopeList.add(deptId);
            }
        }
        dataScopeDeptList = newDataScopeList;
        Map<String, Object> result = Maps.newHashMap();
        result.put("node", allChildrenNode);
        result.put("scope", dataScopeDeptList);
        result.put("pids", parentDeptIdList);
        return result;
    }

    @Override
    public void packgeAllDeptOption() {
        List<DeptTreeDTO> deptList = baseDao.selectListDeptTree();
        JSONObject node;
        JSONArray headNodes = new JSONArray();
        for (DeptTreeDTO deptItemDto : deptList) {
            if (deptItemDto.getPid().longValue() == NumConstant.ZERO_L) {
                node = new JSONObject();
                node.put("value", deptItemDto.getId());
                node.put("label", deptItemDto.getName());
                headNodes.add(node);
            }
        }
        // 用于存放所有父级节点
        JSONArray parent;
        parent = headNodes;
        // 用于存放所有子级节点
        JSONArray allChildren = new JSONArray();
        JSONArray children;
        // 用于存放单个子级节点
        JSONObject childNode;
        // 存放其余未处理的类别(节点)
        List<DeptTreeDTO> others = this.getOtherDept(deptList, parent);

        while (!others.isEmpty()) {
            for (int i = 0; i < parent.size(); i++) {
                node = parent.getJSONObject(i);
                children = new JSONArray();
                for (DeptTreeDTO categoryTreeDto : others) {
                    if (categoryTreeDto.getPid().equals(node.get("value"))) {
                        childNode = new JSONObject();
                        childNode.put("value", categoryTreeDto.getId());
                        childNode.put("label", categoryTreeDto.getName());
                        childNode.put("typeKey", categoryTreeDto.getTypeKey());
                        children.add(childNode);
                        allChildren.add(childNode);
                    }
                }
                if (!children.isEmpty()) {
                    node.put("children", children);
                }
            }
            parent = allChildren;

            others = this.getOtherDept(others, parent);

        }
        //存放到redis中
        List<JSONArray> cache = Lists.newArrayList();
        cache.add(headNodes);
        DeptOption option = new DeptOption();
        option.setOptions(cache.get(0));
        redisUtils.set(RedisKeys.getAllDeptOptionKey(), option);
    }

    List<DeptTreeDTO> getOtherDept(List<DeptTreeDTO> deptList, JSONArray parent) {
        List<Long> already = Lists.newArrayList();
        for (int i = 0; i < parent.size(); i++) {
            already.add((Long) parent.getJSONObject(i).get("value"));
        }

        List<DeptTreeDTO> others = Lists.newArrayList();

        for (DeptTreeDTO categoryTreeDto : deptList) {
            Long categoryTreeDtoId = categoryTreeDto.getId();
            if (!already.contains(categoryTreeDtoId)) {
                others.add(categoryTreeDto);
            }
        }
        return others;
    }


    /***
     *
     * @param
     * @return com.nn.smart.bus.commons.tools.utils.Result<com.nn.smart.bus.dto.DeptOption>
     * @author nanning
     */
    @Override
    public Result<DeptOption> getDeptTree() {
        String deptKey = RedisKeys.getAllDeptOptionKey();
        Object obj = redisUtils.get(deptKey);
        if (null == obj) {
            this.packgeAllDeptOption();
            obj = redisUtils.get(deptKey);
        }
        return new Result<DeptOption>().ok((DeptOption) obj);
    }

    /**
     * @param
     * @return com.nn.smart.bus.commons.tools.utils.Result<com.nn.smart.bus.dto.DeptOption>
     * @author nanning
     * @Description 获取所有部门树:二级只要街道
     **/
    @Override
    public Result<DeptOption> getDeptTreeForEpiDemic() {
        String deptKey = RedisKeys.getAllDeptOptionKeyForEpiDemic();
        Object obj = redisUtils.get(deptKey);
        if (null == obj) {
            this.packgeAllDeptOptionForEpiDemic();
            obj = redisUtils.get(deptKey);
        }
        return new Result<DeptOption>().ok((DeptOption) obj);
    }

    /**
     * @param
     * @return void
     * @author nanning
     * @Description
     * @Date 2020/1/31 11:39
     **/
    private void packgeAllDeptOptionForEpiDemic() {
        List<DeptTreeDTO> deptList = baseDao.selectListDeptTreeForEpiDemic();
        JSONObject node;
        JSONArray headNodes = new JSONArray();
        for (DeptTreeDTO deptItemDto : deptList) {
            if (deptItemDto.getPid().longValue() == NumConstant.ZERO_L) {
                node = new JSONObject();
                node.put("value", deptItemDto.getId());
                node.put("label", deptItemDto.getName());
                headNodes.add(node);
            }
        }
        // 用于存放所有父级节点
        JSONArray parent;
        parent = headNodes;
        // 用于存放所有子级节点
        JSONArray allChildren = new JSONArray();
        JSONArray children;
        // 用于存放单个子级节点
        JSONObject childNode;
        // 存放其余未处理的类别(节点)
        List<DeptTreeDTO> others = this.getOtherDept(deptList, parent);

        while (!others.isEmpty()) {
            for (int i = 0; i < parent.size(); i++) {
                node = parent.getJSONObject(i);
                children = new JSONArray();
                for (DeptTreeDTO categoryTreeDto : others) {
                    if (categoryTreeDto.getPid().equals(node.get("value"))) {
                        childNode = new JSONObject();
                        childNode.put("value", categoryTreeDto.getId());
                        childNode.put("label", categoryTreeDto.getName());
                        children.add(childNode);
                        allChildren.add(childNode);
                    }
                }
                if (!children.isEmpty()) {
                    node.put("children", children);
                }
            }
            parent = allChildren;

            others = this.getOtherDept(others, parent);

        }
        //存放到redis中
        List<JSONArray> cache = Lists.newArrayList();
        cache.add(headNodes);
        DeptOption option = new DeptOption();
        option.setOptions(cache.get(0));
        redisUtils.set(RedisKeys.getAllDeptOptionKeyForEpiDemic(), option);
    }

    @Override
    public Result<DeptOption> getUserDeptOptionByUserId(String userId) {
        Long realUserId = Long.parseLong(userId);
        String deptOptionKey = RedisKeys.getWorkLogUserDeptOptionKey(realUserId);
        Object obj = redisUtils.get(deptOptionKey);
        if (null == obj) {
            this.packageWorkLogsUserDeptOption(realUserId);
            obj = redisUtils.get(deptOptionKey);
        }
        return new Result<DeptOption>().ok((DeptOption) obj);
    }

}
